package org.dtrevien.metamodel.java.visitor.impl.deprecated;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.dtrevien.metamodel.java.Attribut;
import org.dtrevien.metamodel.java.Classe;
import org.dtrevien.metamodel.java.ClasseAggregationReference;
import org.dtrevien.metamodel.java.ClasseCompositionReference;
import org.dtrevien.metamodel.java.ClasseExtendReference;
import org.dtrevien.metamodel.java.ClasseImplementReference;
import org.dtrevien.metamodel.java.Constructeur;
import org.dtrevien.metamodel.java.Import;
import org.dtrevien.metamodel.java.Methode;
import org.dtrevien.metamodel.java.ObjectList;
import org.dtrevien.metamodel.java.Systeme;
import org.dtrevien.metamodel.java.Value;
import org.dtrevien.metamodel.java.visitor.Visitor;

public class JPrettyPrinter extends Visitor {

	protected String str = "";
	protected File root;

	public JPrettyPrinter() {
		this.root = new File("src/out/generated");
		this.root.mkdirs();
	}
	
	private void writeIt(String className, String classContent) throws IOException {
		File f = new File(this.root.getAbsolutePath()+"/"+className+".java");
		BufferedWriter bw = null;
		try {
			f.createNewFile();
			FileWriter fw = new FileWriter(f);
			bw = new BufferedWriter(fw);
			bw.write(classContent);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			bw.close();
		}
	}
	
	private String capitalize(String str) {
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}
	
	@Override
	public void visiteClasse(Classe c) {
		//package
		c.setClasspath(this.root.getPath().replace("src/","").replace("/", "."));
		this.str+="package "+this.root.getPath().replace("src/","").replace("/", ".")+";\n\n";
		
		for (Import im : c.getImports()) {
			im.accept(this);
			this.str+=";\n";
		}
		this.str+="\n";
		
		//class
		if (c.isAbstract()) this.str+="abstract ";
		this.str+="class "+capitalize(c.getName());
		if (c.getExtends().size() > 0) {
			int i=0;
			this.str+=" extends ";
			for (ClasseExtendReference ext : c.getExtends()) {
				ext.accept(this);
				if (i < c.getExtends().size()-1) this.str+=", ";
				i++;
			}
		}
		this.str+=" {\n\n";
		for (Attribut a : c.getAttributs()) {
			this.str+="\tprivate ";
			a.accept(this);
			this.str+=";\n";
		}
		this.str+="\n";
		c.getConstructeur().accept(this);
		this.str+="\n";
		this.str+="}\n";
		
		try {
			writeIt(capitalize(c.getName()), this.str);
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.str = "";
		
	}
	
	@Override
	public void visiteClasseAggregationReference(ClasseAggregationReference c) {
		this.str+=capitalize(c.getType().getName())+" "+c.getName();
		//Add in constructor params and assign it
	}
	

	@Override
	public void visiteClasseCompositionReference(ClasseCompositionReference c) {
		this.str+=capitalize(c.getType().getName())+" "+c.getName();
		//Add 'new' into constructor 
	}

	@Override
	public void visiteObjectList(ObjectList c) {
		this.str+="List<"+capitalize(c.getType().getName())+"> "+c.getName();
	}

	@Override
	public void visiteMethode(Methode v) {
		// TODO Auto-generated method stub
		
	}
	
	
	//--Reference --//
	
	@Override
	public void visiteSystem(Systeme s) {
		for (Classe c : s.getClasses()) {
			c.accept(this);
		}
	}

	@Override
	public void visitImport(Import i) {
		this.str+="import "+i.getClasspath();
	}
	
	

	@Override
	public void visitConstructeur(Constructeur c) {
		this.str+="\tpublic "+capitalize(c.getClassname())+" (";
		int i=0;
		for (Attribut a : c.getAttributs()) {
			a.accept(this);
			if (i < c.getAttributs().size()-1) this.str+=", ";
			i++;
		}
		this.str+=") {\n";
		for (Attribut a : c.getAttributsRef()) {
			this.str+="\t\t";
			a.accept(this);
			this.str+=";\n";
		}
		this.str+="\t}\n";
	}

	@Override
	public void visiteValue(Value c) {
		this.str+=capitalize(c.getType().getName())+" "+c.getName();
	}

	@Override
	public void visiteClasseExtendsReference(ClasseExtendReference c) {
		this.str+=capitalize(c.getName());
	}

	@Override
	public void visiteClasseImplementReference(ClasseImplementReference c) {
		// TODO Auto-generated method stub
		
	}

	
}
